package ru.susu.algebra.matrix;

import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.Arrays;

import org.apache.commons.lang.ArrayUtils;

import ru.susu.algebra.wrapper.number.INumberWrapper;


/**
 * Матрица, состоящая из оберток чисел {@link INumberWrapper}
 *
 * @author akargapolov
 * @since: 14.10.2010
 */
public class NumbersMatrix<T> implements INumberWrapper<NumbersMatrix<T>>
{
	private INumberWrapper<T>[][] _values;

	public NumbersMatrix(INumberWrapper<T>[][] values)
	{
		_values = values;
	}

	public INumberWrapper<T>[][] getValues()
	{
		return _values;
	}

	@Override
	public NumbersMatrix<T> multiply(INumberWrapper<NumbersMatrix<T>> other)
	{
		@SuppressWarnings("unchecked")
		NumbersMatrix<T> res = new NumbersMatrix<T>((INumberWrapper<T>[][])Array.newInstance(_values[0][0].getClass(), _values.length, other.getValue()._values[0].length));
		for (int i = 0;i < _values.length; i++)
		{
			for (int j = 0;j < other.getValue()._values[0].length;j++)
			{
				INumberWrapper<T> value = null;
				for (int k = 0;k < _values[0].length;k++)
				{
					INumberWrapper<T> m = _values[i][k].multiply(other.getValue()._values[k][j]);
					value = (value == null) ? m : value.add(m);
				}
				res._values[i][j] = value;
			}
		}
		return res;
	}

	@Override
	public NumbersMatrix<T> mod(BigInteger mod) throws Exception
	{
		NumbersMatrix<T> res = new NumbersMatrix<T>(_values.clone());
		for (int row = 0;row < res._values.length;row++)
		{
			for (int column =0;column < res._values[0].length; column++)
			{
				res._values[row][column] = _values[row][column].mod(mod);
			}
		}
		return res;
	}

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(_values);
		return result;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		@SuppressWarnings("unchecked")
		NumbersMatrix other = (NumbersMatrix) obj;
		return ArrayUtils.isEquals(_values, other._values);
	}

	@Override
	public NumbersMatrix<T> add(INumberWrapper<NumbersMatrix<T>> other)
	{
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public NumbersMatrix<T> divide(INumberWrapper<NumbersMatrix<T>> other)
	{
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public NumbersMatrix<T> getValue()
	{
		return this;
	}

	@Override
	public long remainder(long val)
	{
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void setValue(Number value)
	{
		// TODO Auto-generated method stub

	}

	@Override
	public NumbersMatrix<T> subtract(INumberWrapper<NumbersMatrix<T>> other)
	{
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String toString()
	{
		return "NumbersMatrix [_values=" + Arrays.toString(_values) + "]";
	}
}
